#include "swinput.h"
#include "utils.h"

using namespace std;
using namespace UTILS;

SWINPUT::SWINPUT()
{
	cout << "h" << endl;
	cin >> horizon;
	//cerr << "horizon" << horizon << endl;
	cout << "c" << endl;
	cin >> NumActions;
	string temp;
	for (int i=0; i < NumActions; i++) {
		cin >> temp;
		actionNames.push_back(temp);
	}

	//cerr << "numActions: " << NumActions << endl;

	cin >> numStateVariables;
	for (int i=0; i < numStateVariables; i++) {
		cin >> temp;
		stateNames.push_back(temp);
	}

	cin >> numObsVariables;
	for (int i=0; i < numObsVariables; i++) {
		cin >> temp;
		obsNames.push_back(temp);
	}

	// Print weightedObsVars
	int obsLength;
	cin >> obsLength;
	weightedObsVars =  new int[obsLength];
	for (int i=0; i < obsLength; i++) {
		cin >> weightedObsVars[i];
	}

	cin >> NumObservations;
    //cerr << "numObservations: " << NumObservations << endl;

    //for (int i=0; i < obsNames.size(); i++)
    	//cerr << obsNames.at(i) << ",";

    RewardRange = 200;
    Discount = 0.95;
    InitGeneral();
}

int SWINPUT::convertToFlatObsState(vector<int> input)
{
	int result = 0;
	for (unsigned int i=0; i < input.size(); i++)
		result += (input.at(i)-1)*weightedObsVars[i];
	return result;
}

void SWINPUT::InitGeneral()
{
    RandomSeed(0);
}

STATE* SWINPUT::Copy(const STATE& state) const
{
    const SWINPUT_STATE& rockstate = safe_cast<const SWINPUT_STATE&>(state);
    SWINPUT_STATE* newstate = MemoryPool.Allocate();
    *newstate = rockstate;
    return newstate;
}

void SWINPUT::Validate(const STATE& state) const
{
    const SWINPUT_STATE& rockstate = safe_cast<const SWINPUT_STATE&>(state);
}

STATE* SWINPUT::CreateStartState() const
{
	cout << "b" << endl;
	int state = -1;
	cin >> state;
    SWINPUT_STATE* rockstate = MemoryPool.Allocate();
    rockstate->state = state;
    return rockstate;
}

void SWINPUT::FreeState(STATE* state) const
{
    SWINPUT_STATE* rockstate = safe_cast<SWINPUT_STATE*>(state);
    MemoryPool.Free(rockstate);
}

bool SWINPUT::Step(STATE& state, int action,
    int& observation, double& reward) const
{
	// if terminal, return true
	cout << "s" << endl;

    SWINPUT_STATE& rockstate = safe_cast<SWINPUT_STATE&>(state);
    cout << rockstate.state << endl;
    cout << action << endl;
    cin >> rockstate.state;
    cin >> observation;
    cin >> reward;

//    // listen
//    if (action == 0) {
//    	reward = -1;
//
//        if (Bernoulli(0.85))
//        	observation = rockstate.state;
//        else
//        	observation = 1-rockstate.state;
//
//    }
//    // open-left
//    if (action == 1) {
//    	// state is left
//    	if (rockstate.state == 0) reward = 10;
//    	else reward = -100;
//
//        if (Bernoulli(0.5))
//        	rockstate.state = 0;
//        else
//        	rockstate.state = 1;
//
//        if (Bernoulli(0.5))
//        	observation = 0;
//        else
//        	observation = 1;
//       // return true;
//
//    }
//    // open-right
//    if (action == 2) {
//    	// state is left
//    	if (rockstate.state == 0) reward = -100;
//    	else reward = 10;
//
//        if (Bernoulli(0.5))
//        	rockstate.state = 0;
//        else
//        	rockstate.state = 1;
//
//        if (Bernoulli(0.5))
//        	observation = 0;
//        else
//        	observation = 1;
//        //return true;
//    }

    return false;
}


void SWINPUT::DisplayBeliefs(const BELIEF_STATE& beliefState,
    std::ostream& ostr) const
{
}

void SWINPUT::DisplayState(const STATE& state, std::ostream& ostr) const
{
    const SWINPUT_STATE& rockstate = safe_cast<const SWINPUT_STATE&>(state);
    ostr << "State:" << rockstate.state;
    ostr << endl;
}

void SWINPUT::DisplayObservation(const STATE& state, int observation, std::ostream& ostr) const
{
    ostr << "Observation:" << observation << endl;
}

void SWINPUT::DisplayAction(int action, std::ostream& ostr) const
{
	ostr << "Action:" << action << endl;
}
